package org.babygo.file.handler;

import com.ape.babygo.api.BasePackage;
import com.ape.babygo.api.RecevieHandler;
import com.babygo.transport.api.FileChooseHandler;
import org.babygo.file.FilePool;
import org.babygo.file.protocol.FilePackage;
import org.babygo.net.test.TestSender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class FileMsgHandler implements RecevieHandler {
    private static Logger logger = LoggerFactory.getLogger(FileMsgHandler.class);

    private FileChooseHandler fileChooseHandler;
    private static byte[] LOCKER = new byte[0];

    public FileMsgHandler(FileChooseHandler fileChooseHandler) {
        this.fileChooseHandler = fileChooseHandler;
    }

    @Override
    public void handle(BasePackage basePackage) {
        downLoadFile(basePackage);
    }

    void downLoadFile(BasePackage basePackage) {
        logger.info("收到文件包!");
        FilePackage filePackage = new FilePackage();
        filePackage.deserialization(basePackage.getData());
        FilePool.saveFileData(filePackage.getSessionId(), (int) filePackage.getTotalNum(), filePackage.getPackageIndex(), filePackage);
        if (filePackage.getPackageIndex() == 0) {
            startDownLoadThread(filePackage.getSessionId(), (int) filePackage.getTotalNum());
            logger.info("一共有:" + filePackage.getTotalNum() + "个待接收的文件包!");
        }
    }

    private void startDownLoadThread(short id, int totalNum) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < totalNum; i++) {
                    FilePackage filePackage = FilePool.getFilePackage(id, i);
                    if (filePackage == null) {
                        i--;
                        continue;
                    } else {
                        doDownLoadFile(id, filePackage);
                        if ((i + 1) == totalNum) {
                            logger.info("文件下载完成!");
                            FilePool.closeFile(id);
                        }
                    }
                }
            }
        }).start();
    }

    private void doDownLoadFile(short fileId, FilePackage filePackage) {
        File localFile = getFile(fileId);
        RandomAccessFile accessFile = getRandomAccessFile(fileId, localFile);
        long pos = FilePool.getFileLength(fileId);
        try {
            accessFile.seek(pos);
            accessFile.write(filePackage.getData());
            FilePool.fileWriteLength(fileId, filePackage.getData().length);
            logger.info("本次下载完成!");
        } catch (Exception e) {
            logger.error("下载文件失败!", e);
        }
    }

    private File getFile(short fileId) {
        File file = FilePool.getFile(fileId);
        if (file == null) {
            file = fileChooseHandler.chooseFile();
            logger.info("准备创建文件:" + file.getAbsoluteFile() + ":" + file.getName());
            if (!file.exists()) {
                try {
                    if (file.createNewFile()) {
                        logger.info("创建文件成功!");
                    }
                } catch (IOException e) {
                    logger.info("创建文件失败!");
                    return null;
                }
            } else {
                logger.info("文件已经创建!");
            }
            FilePool.putNewFile(fileId, file);
            return file;
        }
        logger.info("文件已经存在, 直接返回该文件!");
        return file;
    }

    private RandomAccessFile getRandomAccessFile(short fileId, File localFile) {
        RandomAccessFile accessFile = FilePool.getRandomAccessFile(fileId);
        if (accessFile == null) {
            try {
                accessFile = new RandomAccessFile(localFile, "rw");
            } catch (FileNotFoundException e) {
                logger.error("random file not find!", e);
            }
            FilePool.putNewRandomAccessFile(fileId, accessFile);
            return accessFile;
        }
        return accessFile;
    }
}